package com.example.springboot.init;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.StringUtils;


import javax.sql.DataSource;

/**
 * 单数据源配置
 *
 * <p> 数据源类型选用了 Hikari。
 *
 * <p> ConditionalOnProperty: 从配置文件中获取属性，在本文中，当指定属性值是single时，进行实例化。
 * <p>
 *
 * @author Zhang.Z
 * @version 2025-09-22
 */
@Configuration
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "single",
        matchIfMissing = true)
public class SingleJdbcConfig {


    /**
     * dataSource配置。
     * 可使用一下代码自己构建，或者使用spring自动装配的
     */
    @Bean
    public DataSource dataSource(DataSourceProperties properties) {

        //  return springBootBuild(properties);
        return configBuild(properties);
    }


    /**
     * NamedParameterJdbcTemplate
     */
    @Bean
    public NamedParameterJdbcTemplate namedJdbcTemplate(DataSource ds) {
        NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(ds);
        return jdbcTemplate;
    }

    /**
     * JdbcTemplate
     */
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource ds) {
        return new JdbcTemplate(ds);
    }

    /**
     * 方式一:  参考spring-boot代码,利用反射机制,创建dataSource对象
     *
     * @see org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari
     */
    private DataSource springBootBuild(DataSourceProperties properties) {
        HikariDataSource dataSource = DataSourceBuilder.create()
                .type(properties.getType())
                .driverClassName(properties.determineDriverClassName())
                .url(properties.getUrl()).username(properties.getUsername()).password(properties.getPassword())
                .type(HikariDataSource.class)
                .build();

        if (StringUtils.hasText(properties.getName())) {
            dataSource.setPoolName(properties.getName());
        }
        return dataSource;
    }

    /**
     * 方式二: 基于hikariCP属性，创建dataSource
     */
    private DataSource configBuild(DataSourceProperties prop) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(prop.getUrl());
        hikariConfig.setUsername(prop.getUsername());
        hikariConfig.setPassword(prop.getPassword());
        hikariConfig.setDriverClassName(prop.getDriverClassName());
        hikariConfig.setPoolName(prop.getName());
        return new HikariDataSource(hikariConfig);
    }


}
